//
// Created by shiminli on 2024/1/3.
//

#include "accounts.h"



AccountsColumnName accounts::names;
vector<string> accounts::columns = { names.user_id, names.account, names.password, names.phone_number, names.area_code,names.email, names.nickname,
                                 names.face_url,names.gender,names.create_time,names.change_time, names.birth_time,names.level, names.allow_vibration,
                                 names.allow_beep, names.allow_add_friend, names.global_recv_msg_opt
};
//accounts::columns
/**
 CREATE TABLE `accounts` (
  `user_id` bigint unsigned NOT NULL,
  `account` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `phone_number` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `area_code` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `email` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `face_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `gender` int DEFAULT NULL,
  `create_time` datetime(3) DEFAULT NULL,
  `change_time` datetime(3) DEFAULT NULL,
  `birth_time` datetime(3) DEFAULT NULL,
  `level` int DEFAULT '1',
  `allow_vibration` int DEFAULT '1',
  `allow_beep` int DEFAULT '1',
  `allow_add_friend` int DEFAULT '1',
  `global_recv_msg_opt` int DEFAULT '0',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 */
int accounts::insert(Accounts &data) {
    vector<string> insertColumns = {names.account, names.password, names.phone_number, names.area_code, names.nickname,
                              names.create_time,names.change_time, names.birth_time};
    vector<ValuePair> values { ValuePair(true, data.phone_number),ValuePair(true, data.password),
                               ValuePair(true, data.phone_number), ValuePair(true, data.area_code),
                                ValuePair(true, data.nickname), ValuePair(true, data.create_time, true),
                                ValuePair(true, data.change_time, true),
                                ValuePair(true, data.birth_time, true)
    };
    string cmd = SQLBuilder::insertSql(names.tabName, insertColumns, values);
    int ret = SQLHelper::getInstance()->executeUpdate(cmd.c_str());
    return ret == 0;
}

std::optional<Accounts> accounts::queryById(const long &user_id) {
    string cmd = "SELECT * FROM "+names.tabName + " where "+names.user_id +"="+ to_string(user_id);
    MYSQL_RES *res = SQLHelper::getInstance()->executeQuery(cmd.c_str());
    unsigned int fields = mysql_num_fields(res);
    cout<<"queryById rowCount: "<< res->row_count <<endl;
    if (res->row_count < 1 || fields != columns.size()){
        return std::nullopt;
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    Accounts acc{};
    rowToStruct(row, acc);
    mysql_free_result(res);
    return acc;
}

std::optional<Accounts> accounts::queryByPhoneNumber(const std::string &phone_number) {
    string cmd = "SELECT * FROM "+names.tabName + " where "+names.phone_number +"="+ phone_number + " limit 1";
    MYSQL_RES *res = SQLHelper::getInstance()->executeQuery(cmd.c_str());
    unsigned int fields = mysql_num_fields(res);
    cout<<"queryByPhoneNumber rowCount: "<< res->row_count <<endl;
    if (res->row_count < 1 || fields != columns.size()){
        return std::nullopt;
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    Accounts acc{};
    rowToStruct(row, acc);
    mysql_free_result(res);
    return acc;
}

long accounts::queryUserIdByPhoneNumber(const std::string &phone_number) {
    string cmd = "SELECT user_id FROM "+names.tabName + " where "+names.phone_number +"="+ phone_number;
    MYSQL_RES *res = SQLHelper::getInstance()->executeQuery(cmd.c_str());
    cout<<"queryUserIdByPhoneNumber rowCount: "<< res->row_count <<endl;
    if (res->row_count == 0){
        return 0;
    }
    MYSQL_ROW row = mysql_fetch_row(res);
    long id = row[0] ? stol(row[0]) : 0;
    mysql_free_result(res);
    return id;
}

void accounts::rowToStruct(const MYSQL_ROW &row,Accounts &acc) {
    try {
        acc.user_id = row[0] ? stol(row[0]) : 0;
        acc.account = row[1] ? row[1] : "";
        acc.password = row[2] ? row[2] : "";
        acc.phone_number = row[3] ? row[3] : "";
        acc.area_code = row[4] ? row[4] : "";
        acc.email = row[5] ? row[5] : "";
        acc.nickname = row[6] ? row[6] : "";
        acc.face_url = row[7] ? row[7] : "";
        acc.gender = row[8] ? stoi(row[8]) : 0;
        acc.create_time = row[9] ? row[9] : "";
        acc.change_time = row[10] ? row[10] : "";
        acc.birth_time = row[11] ? row[11] : "";
        acc.level = row[12] ? stoi(row[12]) : 1;
        acc.allow_vibration = row[13] ? stoi(row[13]) : 1;
        acc.allow_beep = row[14] ? stoi(row[14]) : 1;
        acc.allow_add_friend = row[15] ? stoi(row[15]) : 1;
        acc.global_recv_msg_opt = row[16] ? stoi(row[16]) : 0;
    } catch (const std::exception& e) {
        // 处理转换异常，可以记录日志或者抛出异常
        // 这里简单地将所有字段置为空或者默认值
        acc = Accounts{0}; // 重置为默认值
    }
}
